﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using DynORM.Interfaces;
using DynORM.ValueObjects;
using DynORM.TypeMappingSubsystem;

namespace DynORM.Interfaces
{


    public class Comparison : IORMComparison
    {
        private readonly string fieldName;
        private readonly ORMComparisonOperator condition;
        private readonly object value;

        public Comparison(string fieldName, ORMComparisonOperator condition, object value)
        {
            this.fieldName = fieldName;
            this.condition = condition;
            this.value = value;
        }

        public void CheckCorrespondenceToRowDescriptor(IRowDescriptor rowDescriptor)
        {
            if (!rowDescriptor.ContainsField(this.FieldName))
                throw new Exception("Field used in predicate is not defined in used row structure.");

            IFieldDescriptor fd = rowDescriptor.GetField(this.FieldName);
            if (this.value != null && !Types.GetCLRCompatibleTypes(this.value.GetType()).Any<Type>(t => t == fd.FieldType))
                throw new Exception("Field's type and compared value's type do not correspond each other.");
        }

        public void CheckInjections()
        {
            //raw implementaion, more advanced logic will be implemented
            string valueStr = value.ToString();

            if (Regex.IsMatch(valueStr, @".*DROP.*", RegexOptions.IgnoreCase) 
                || Regex.IsMatch(valueStr, @".*GRANT.*", RegexOptions.IgnoreCase)
                || Regex.IsMatch(valueStr, @".*INSERT.*", RegexOptions.IgnoreCase)
                || Regex.IsMatch(valueStr, @".*UPDATE.*", RegexOptions.IgnoreCase)
                || Regex.IsMatch(valueStr, @".*DELETE.*", RegexOptions.IgnoreCase)
                || Regex.IsMatch(valueStr, @".*SELECT.*", RegexOptions.IgnoreCase))
                throw new Exception("Value contains injected code.");
        }

        public string FieldName
        {
            get
            {
                return this.fieldName;
            }
        }

        public ORMComparisonOperator Condition
        {
            get
            {
                return this.condition;
            }
        }

        public object Value
        {
            get
            {
                return this.value;
            }
        }

        #region Value-based equality semantics implementation
		public override bool Equals(object obj)
        {
            Comparison that;
            if (obj is Comparison)
                that = (Comparison)obj;
            else
                return false;

            if (String.Compare(that.FieldName, this.fieldName, StringComparison.OrdinalIgnoreCase) == 0 && that.Condition == this.condition && this.Value.Equals(that.value))
                return true;
            else
                return false;
        }

        public override int GetHashCode()
        {
            return this.FieldName.GetHashCode();
        }

        public static bool operator ==(Comparison obj1, Comparison obj2)
        {
            if (!Object.ReferenceEquals(obj1, null))
                return obj1.Equals(obj2);
            else
                return false;
        }

        public static bool operator !=(Comparison obj1, Comparison obj2)
        {
            if (!Object.ReferenceEquals(obj1, null))
                return !obj1.Equals(obj2);
            else
                return false;
        }

	    #endregion
    }
}
